#include "utils.h"

#define MAX_CLIENTS 100 // 最大客户端数
#define MAX_ROOMS 10    // 最大聊天室数量

socklen_t server_addr_len;        // 服务器地址长度
struct sockaddr_in server_addrin; // 服务器地址结构体

// 客户端信息结构体
typedef struct
{
    struct sockaddr_in addr; // 客户端地址
    int room_id;             // 客户端所在的聊天室ID
} Client;

// 聊天室信息结构体
typedef struct
{
    int room_id;                 // 聊天室ID
    char room_name[50];          // 聊天室名称
    int client_count;            // 当前聊天室的客户端数量
    Client clients[MAX_CLIENTS]; // 当前聊天室的客户端列表
} ChatRoom;

// UDP数据包结构体
typedef struct
{
    char time[15];  // 时间
    int SYN;        // 请求类型
    int room_id;    // 聊天室ID
    char name[31];  // 用户名
    char data[1024]; // 消息内容
} UDP_data;

ChatRoom chat_rooms[MAX_ROOMS]; // 聊天室数组
int server_fd;                  // 服务器文件描述符
int room_count = 0;             // 当前聊天室的数量

// 初始化服务器
int UDP_Init_Server(in_port_t port, const char *s_addr)
{
    server_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (server_fd == -1)
    {
        perror("socket error");
        exit(-1);
    }

    server_addrin.sin_family = AF_INET;                // 地址族
    server_addrin.sin_port = htons(port);              // 端口号
    server_addrin.sin_addr.s_addr = inet_addr(s_addr); // IP地址
    server_addr_len = sizeof(server_addrin);           // 结构体大小

    if (bind(server_fd, (struct sockaddr *)&server_addrin, server_addr_len) == -1)
    {
        perror("bind error");
        exit(-1);
    }

    return server_fd;
}

// 广播当前聊天室列表给特定客户端
void send_room_list(int client_fd, struct sockaddr_in *client_addr)
{
    UDP_data room_list_msg;                           // UDP数据包
    memset(&room_list_msg, 0, sizeof(room_list_msg)); // 初始化数据包

    if (room_count == 0)
    {
        strcpy(room_list_msg.data, "当前暂无聊天室!\n");
    }
    else
    {
        strcpy(room_list_msg.data, "当前聊天室列表:\n");
    }

    for (int i = 0; i < room_count; i++)
    {
        char room_info[100]; // 临时存储房间信息
        sprintf(room_info, "%s聊天室ID: %d, 名称: %s, 成员数: %d%s\n", YELLOW, chat_rooms[i].room_id, chat_rooms[i].room_name, chat_rooms[i].client_count, RESET);
        strcat(room_list_msg.data, room_info); // 将信息拼接到数据包
    }

    // 发送给特定客户端
    sendto(client_fd, &room_list_msg, sizeof(room_list_msg), 0, (struct sockaddr *)client_addr, sizeof(*client_addr));
}

// 创建新聊天室
void create_new_room(UDP_data *msg, struct sockaddr_in *client_addr)
{
    if (room_count >= MAX_ROOMS)
    {
        printf("无法创建更多聊天室，达到最大数量！\n");
        return;
    }

    // 创建新房间
    ChatRoom *new_room = &chat_rooms[room_count];
    new_room->room_id = room_count;
    strcpy(new_room->room_name, msg->data); // 设置房间名称
    new_room->client_count = 0;

    printf("room_id=: %d\n", room_count);

    room_count++;
    printf("新聊天室创建: %s\n", new_room->room_name);

    // 添加创建者到聊天室
    new_room->clients[new_room->client_count].addr = *client_addr;
    new_room->clients[new_room->client_count].room_id = new_room->room_id;
    new_room->client_count++;

    // 发送加入成功的消息给创建者
    UDP_data response;                      // 响应消息
    memset(&response, 0, sizeof(response)); // 清空响应
    sprintf(response.data, "%s已创建并加入新聊天室: %s%s\n", YELLOW, new_room->room_name, RESET);
    response.SYN = 1; // 标识成功创建并加入
    response.room_id = new_room->room_id;
    sendto(server_fd, &response, sizeof(response), 0, (struct sockaddr *)client_addr, sizeof(*client_addr));
    return;
}

// 广播消息给聊天室中的所有客户端
void broadcast_message(UDP_data *msg, int room_id)
{
    if (room_id >= 0 && room_id < room_count)
    { // 确保 room_id 合法
        ChatRoom *room = &chat_rooms[room_id];
        for (int i = 0; i < room->client_count; i++)
        {
            sendto(server_fd, msg, sizeof(*msg), 0, (struct sockaddr *)&room->clients[i].addr, sizeof(room->clients[i].addr));
        }
    }
    else
    {
        printf("无效的聊天室 ID:%d\n", room_id);
        return;
    }
    return;
}

// 从聊天室中移除客户端
void remove_client(struct sockaddr_in *client_addr, int room_id)
{
    if (room_id >= 0 && room_id < room_count)
    {
        ChatRoom *room = &chat_rooms[room_id];
        for (int i = 0; i < room->client_count; i++)
        {
            if (memcmp(&room->clients[i].addr, client_addr, sizeof(*client_addr)) == 0)
            {
                // 移动最后一个客户端到当前位置
                room->clients[i] = room->clients[room->client_count - 1];
                room->client_count--;
                break;
            }
        }
    }
    else
    {
        printf("无效的聊天室 ID:%d\n", room_id);
        return;
    }
    return;
}

// 处理客户端消息的线程
void *handle_client(void *arg)
{
    UDP_data server_data; // 服务器接收到的UDP数据包
    while (1)
    {
        memset(&server_data, 0, sizeof(server_data)); // 清空数据包
        struct sockaddr_in client_addr;               // 客户端地址
        socklen_t client_len = sizeof(client_addr);   // 地址长度

        // 接收消息
        recvfrom(server_fd, &server_data, sizeof(server_data), 0, (struct sockaddr *)&client_addr, &client_len);

        // 客户端请求获取聊天室列表
        if (server_data.SYN == 0)
        { // SYN=0 表示请求获取聊天室列表
            send_room_list(server_fd, &client_addr);
        }
        // 客户端请求创建聊天室
        else if (server_data.SYN == 4)
        { // SYN=4 表示创建聊天室
            create_new_room(&server_data, &client_addr);
        }
        // 客户端请求加入聊天室
        else if (server_data.SYN == 1)
        {
            int room_id = server_data.room_id; // 客户端请求的聊天室ID

            if (room_id >= 0 && room_id < room_count)
            {
                ChatRoom *room = &chat_rooms[room_id];

                // 检查该客户端是否已经在该聊天室
                int already_in_room = 0;
                for (int i = 0; i < room->client_count; i++)
                {
                    if (memcmp(&room->clients[i].addr, &client_addr, sizeof(client_addr)) == 0)
                    {
                        already_in_room = 1;
                        break;
                    }
                }

                if (!already_in_room)
                {
                    room->clients[room->client_count].addr = client_addr;
                    room->clients[room->client_count].room_id = room_id;
                    room->client_count++;
                }

                // 发送欢迎信息
                sprintf(server_data.data, "%s%s 加入了聊天室 %s%s", YELLOW, server_data.name, room->room_name, RESET);
                broadcast_message(&server_data, room_id);
            }
        }
        // 处理普通聊天消息
        else if (server_data.SYN == 2)
        {                                      // SYN=2 表示普通聊天消息
            int room_id = server_data.room_id; // 从客户端数据中获取聊天室ID
            if (room_id >= 0 && room_id < room_count)
            {
                broadcast_message(&server_data, room_id);
            }
        }
        // 处理客户端退出
        else if (server_data.SYN == 3)
        {                                      // SYN=3 表示退出
            int room_id = server_data.room_id; // 从客户端数据中获取聊天室ID
            printf("%s 已退出聊天室 %d\n", server_data.name, room_id);
            sprintf(server_data.data, "%s%s 已退出聊天室 %d%s", RED, server_data.name, room_id, RESET);
            broadcast_message(&server_data, room_id);
            remove_client(&client_addr, room_id);
        }
    }
    return NULL;
}

int main(int argc, char const *argv[])
{
    int server_fd = UDP_Init_Server(8888, "192.168.10.4");
    // 启动消息处理线程
    pthread_t tid;                                   // 线程ID
    pthread_create(&tid, NULL, handle_client, NULL); // 创建线程
    pthread_join(tid, NULL);                         // 等待线程结束
    close(server_fd);                                // 关闭服务器文件描述符
    return 0;
}
